package com.fjc.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fjc.dao.SysPermissionMapper;
import com.fjc.dao.SysUserLogMapper;
import com.fjc.dao.SysUserMapper;
import com.fjc.dao.SysUserPermissionMapper;
import com.fjc.domain.*;
import com.fjc.service.SysUserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * Created by fjc on 2018/9/24.
 */
@Service
public class SysUserServiceImpl implements SysUserService {
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysPermissionMapper permissionMapper;
    @Autowired
    private SysUserLogMapper sysUserLogMapper;
    @Autowired
    private SysUserPermissionMapper sysUserPermissionMapper;

    @Override
    public ResultObject login(String username, String password, boolean rememberMe, HttpServletRequest request) {
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password,rememberMe);
        Subject subject = SecurityUtils.getSubject();
        String ip = request.getRemoteAddr();
        SysUserLog sysUserLog = new SysUserLog();
        sysUserLog.setIp(ip);
        sysUserLog.setUsername(username);
        try{
            subject.login(usernamePasswordToken);
            SecurityUtils.getSubject().getSession().setTimeout(1800000);
            sysUserLog.setLoginResult(1);
            sysUserLog.setReason("");
            sysUserLogMapper.insertSelective(sysUserLog);
            return new ResultObject(0,"登录成功");
        }catch (IncorrectCredentialsException e){
            sysUserLog.setLoginResult(0);
            sysUserLog.setReason("账号或密码错误");
            sysUserLogMapper.insertSelective(sysUserLog);
            return new ResultObject(1,"账号或密码错误");
        }catch (LockedAccountException e){//一系列抛出的异常可以在这里捕获进行处理。可能比较适合前后端分离的项目，还有异常捕获是不是和trycatch冲突了，好像一般都是返回提示比较多，等缓存过期了就可以在此尝试登录了
            return new ResultObject(1,"账号已被锁定");
        } catch (ExcessiveAttemptsException e){//一系列抛出的异常可以在这里捕获进行处理。可能比较适合前后端分离的项目，还有异常捕获是不是和trycatch冲突了，好像一般都是返回提示比较多，等缓存过期了就可以在此尝试登录了
            sysUserLog.setLoginResult(0);
            sysUserLog.setReason("登录失败次数过多");
            sysUserLogMapper.insertSelective(sysUserLog);
            return new ResultObject(1,"登录失败次数过多，请10分钟后再登录");
        } catch (DisabledAccountException e){//一系列抛出的异常可以在这里捕获进行处理。可能比较适合前后端分离的项目，还有异常捕获是不是和trycatch冲突了，好像一般都是返回提示比较多，等缓存过期了就可以在此尝试登录了
            return new ResultObject(1,"帐号已被禁用");
        } catch (ExpiredCredentialsException e){//一系列抛出的异常可以在这里捕获进行处理。可能比较适合前后端分离的项目，还有异常捕获是不是和trycatch冲突了，好像一般都是返回提示比较多，等缓存过期了就可以在此尝试登录了
            return new ResultObject(1,"帐号已过期");
        } catch (UnknownAccountException e){//一系列抛出的异常可以在这里捕获进行处理。可能比较适合前后端分离的项目，还有异常捕获是不是和trycatch冲突了，好像一般都是返回提示比较多，等缓存过期了就可以在此尝试登录了
            sysUserLog.setLoginResult(0);
            sysUserLog.setReason("帐号不存在");
            sysUserLogMapper.insertSelective(sysUserLog);
            return new ResultObject(1,"帐号不存在");
        } catch (UnauthorizedException e){//一系列抛出的异常可以在这里捕获进行处理。可能比较适合前后端分离的项目，还有异常捕获是不是和trycatch冲突了，好像一般都是返回提示比较多，等缓存过期了就可以在此尝试登录了
            return new ResultObject(1,"您没有得到相应的授权");
        } catch (Exception e){
            e.printStackTrace();
            sysUserLog.setLoginResult(0);
            sysUserLog.setReason("出错了");
            sysUserLogMapper.insertSelective(sysUserLog);
            return new ResultObject(1,"出错了");
        }
    }

    public SysUser findUserByUsername(String username){
        SysUserExample userExample = new SysUserExample();
        SysUserExample.Criteria criteria = userExample.createCriteria();
        criteria.andUsernameEqualTo(username);
        List<SysUser> list = sysUserMapper.selectByExample(userExample);
        if(list.size() > 0){
            return list.get(0);
        }
        return null;
    }

    @Override
    public Set<Map> findUserRoleByUsername(String username) {
        Set<Map> list = sysUserMapper.selectRolesByUsername(username);
        return list;
    }

    @Override
    public Set<Map> findRolePermissionByRole(Set<Map> roles) {
        Set<Map> list = permissionMapper.selectPermissionsByRoles(roles);
        return list;
    }

    public ResultObject getNavPermissions(){
        SysUser user = (SysUser) SecurityUtils.getSubject().getSession().getAttribute("userInfo");
        List<Map> list = sysUserMapper.selectPermissionsById(user.getId());
        //这边只适用于最多二级菜单，再多要改代码
        List<Map> parentList = new ArrayList<>();
        List<Map> childrensList = new ArrayList<>();
        for(Map map:list){
            if(map.get("parent_id") == null){
                //为空
                parentList.add(map);
            }else{
                childrensList.add(map);
            }
        }
        for(Map pMap:parentList){
            List<Map> childrenList = new ArrayList<>();
            for(Map map:childrensList){
                if(map.get("parent_id").toString().equals(pMap.get("permission_id").toString())){
                    childrenList.add(map);
                }
            }
            pMap.put("children",childrenList);
        }

        return new ResultObject(0,"成功",parentList);
    }

    @Override
    public ResultObject getLoginLog(Integer page,Integer limit) {
        if(page > 0){limit = page * limit;}
        List<Map> list = sysUserLogMapper.selectAllLimit(page,limit);
        SysUserLogExample sysUserLogExample = new SysUserLogExample();
        int size = (int)sysUserLogMapper.countByExample(sysUserLogExample);
        return new ResultObject(0,"成功",list,size);
    }

    @Override
    public ResultObject getUsersInfo(Integer page, Integer limit) {
        if(page > 0){limit = page * limit;}
        List<Map> list = sysUserMapper.selectAllLimit(page,limit);
        return new ResultObject(0,"成功",list,list.size());
    }

    @Override
    public ResultObject delUsersInfo(Integer id) {
        sysUserMapper.deleteByPrimaryKey(id);
        return new ResultObject(0,"成功");
    }

    @Override
    public ResultObject saveUser(SysUser sysUser) {
        if(sysUser.getId() == null){
            //新增操作
            sysUser.setStatus(1);
            sysUserMapper.insertSelective(sysUser);
        }else{
            //更新操作
            sysUserMapper.updateByPrimaryKeySelective(sysUser);
        }
        return new ResultObject(0,"成功");
    }

    @Override
    public ResultObject getUserPermissions(Integer id) {
        //获取一级菜单
        List<Map> list = sysUserPermissionMapper.selectParentMenuByUserid(id);
        //获取每个一级菜单下的二级菜单
        for (Map map:list){
            List<Map> childrenList = sysUserPermissionMapper.selectChildrenMenuByUserid(id,(int)map.get("pid"));
            if(childrenList.size() > 0){
                map.put("children",childrenList);
            }
        }

        List<Map> idMapList = sysUserPermissionMapper.selectNoDelPermissionByUserid(id);
        List<Integer> idList = new ArrayList<>();
        for(Map map: idMapList){
            if(map.get("parent_id") != null) {
                idList.add((int)map.get("parent_id"));
            }
        }

        List<Integer> checkNode = new ArrayList<>();
        if(idList.size() > 0){
            for(Map map: idMapList){
                for(Integer pid : idList){
                    if((int)map.get("permission_id") != pid) {
                        checkNode.add((int)map.get("id"));
                    }
                }
            }
        }else{
            for(Map map: idMapList){
                checkNode.add((int)map.get("id"));
            }
        }

        Map<String ,Object> returnMap = new HashMap<>();
        returnMap.put("treeData",list);
        returnMap.put("checkNode",checkNode);
        return new ResultObject(0,"",returnMap);
    }

    @Override
    public ResultObject updatePermissionsByUserId(JSONObject object) {
        JSONArray checkNodes = object.getJSONArray("keys");
        Integer userid = object.getInteger("userid");

        //获取该用户所有权限id
        List<Integer> allPermissionIds = sysUserPermissionMapper.selectAllPermissionByUserid(userid);

        List<Integer> checkedPermissinsIds = checkNodes.toJavaList(Integer.class);
        for(Integer id: checkedPermissinsIds){
            SysUserPermission sysUserPermission = new SysUserPermission();
            sysUserPermission.setId(id);
            sysUserPermission.setStatus(1);
            sysUserPermissionMapper.updateByPrimaryKeySelective(sysUserPermission);
        }

        //与现在选择的权限id比较，生成已经取消的权限id
        allPermissionIds.removeAll(checkedPermissinsIds);

        //更新取消的权限id
        for(Integer id:allPermissionIds){
            SysUserPermission sysUserPermission = new SysUserPermission();
            sysUserPermission.setId(id);
            sysUserPermission.setStatus(0);
            sysUserPermissionMapper.updateByPrimaryKeySelective(sysUserPermission);
        }

        //更新有父级的权限
        for(int j=0;j< checkNodes.size();j++){
            List<Map> hasParent = sysUserPermissionMapper.selectParentIsNotNull(checkNodes.getInteger(j));
            if(hasParent.size() > 0){
                for(Map map : hasParent){
                    SysUserPermission sysUserPermission = new SysUserPermission();
                    sysUserPermission.setStatus(1);
                    SysUserPermissionExample sysUserPermissionExample = new SysUserPermissionExample();
                    SysUserPermissionExample.Criteria criteria = sysUserPermissionExample.createCriteria();
                    criteria.andPermissionIdEqualTo((int)map.get("parent_id"));
                    sysUserPermissionMapper.updateByExampleSelective(sysUserPermission,sysUserPermissionExample);
                }
            }
        }

        return new ResultObject(0,"成功");
    }

}
